using System;
using System.Collections.Generic;
using System.Linq;
using SharpArch.Core.DomainModel;
using NHibernate.Validator.Constraints;

namespace Peak.Core
{
  public class Project : Entity
  {
    public Project()
    {
      Sprints = new List<Sprint>();
      Stories = new List<Story>();
      Users = new List<User>();
      Burndown = new List<ProjectBacklogEntry>();
      Calendar = new Calendar(); 
    }

    public virtual Calendar Calendar { get; set; }

    [NotNullNotEmpty]
    public virtual string Name { get; set; }
    [NotEmpty]
    public virtual string Vision { get; set; }
    [NotEmpty]
    public virtual string DefinitionOfDone { get; set; }

    public virtual IList<ProjectBacklogEntry> Burndown { get; set; }

    public virtual DateTime Start { get; set; }
    public virtual DateTime End { get; set; }

    public virtual DateTime Created { get; set; }
    [NotNullNotEmpty]
    public virtual string CreatedBy { get; set; }
    
    [Min(0)]
    public virtual double StoryPoints { get; set; }

    public virtual IList<Sprint> Sprints{get; set;}
    public virtual IList<Story> Stories { get; set; }
    public virtual IList<User> Users { get; set; }
    public virtual Sprint CurrentSprint { get; set; }
    public virtual TimeSpan CurrentEffort { get; set; }

    public virtual void AddStory(Story story)
    {
      Stories.Add(story);
      story.Project = this;
      StoryPoints += story.StoryPoints;      
    }

    public virtual void RemoveStory(Story story)
    {
      Stories.Remove(story);
      story.Project = null;
      StoryPoints -= story.StoryPoints;
      if(story.SprintStories.FirstOrDefault(f=>f.Sprint != null) != null)
      {
        throw new StoryAddedToSprint();
      }      
    }

    public virtual void AddSprint(Sprint sprint)
    {
      if (CurrentSprint != null && sprint.Status != SprintStatus.Finished)
        throw new OnlyOneOngoingSprintException();

      if (sprint.Status != SprintStatus.Finished)
        CurrentSprint = sprint;

      Sprints.Add(sprint);
      sprint.Project = this;      
    }

    public virtual void RemoveSprint(Sprint sprint)
    {
      if(CurrentSprint == sprint)
        CurrentSprint = null;

      Sprints.Remove(sprint);
      sprint.Project = null;
    }
  }
}